package com.zy.explore.client.infrastructure.util;

import com.zy.explore.client.infrastructure.util.mock.FakerDataProvider;
import com.zy.explore.client.infrastructure.util.mock.MockProperty;
import com.zy.explore.client.interfaces.vo.PageVO;
import com.zy.explore.client.interfaces.vo.ResultVO;
import uk.co.jemos.podam.api.PodamFactoryImpl;

import java.lang.reflect.Type;
import java.util.List;

/**
 * description 模拟 POJO
 * 1. 使用模拟数据填充 POJO 返回
 * 2. 常见属性名返回更真实的模拟数据（如 username / address）
 * 3. 通过注解 {@link MockProperty} 使用 {@link com.github.javafaker.Faker} 方法指定特殊模拟规则
 *
 * @author 🇨🇳中国印🇨🇳
 * @date 2022年04月17日 02:38:46
 */
public class MockBeanUtil {

    private final static PodamFactoryImpl FACTORY = new PodamFactoryImpl(new FakerDataProvider());

    private MockBeanUtil() {
    }

    /**
     * 模拟填充 POJO 返回
     *
     * 使用方式
     * 1. 不需要范型
     * mock(MockBean.class)
     * 2. 需要范型
     * mock(List.class, MockBean.class)
     *
     * @param clazz           需要 Mock 的类
     * @param genericTypeArgs 范型类
     * @param <T>             返回类型
     * @return POJO 实例
     */
    public static <T> T mock(Class<T> clazz, Type... genericTypeArgs) {
        return FACTORY.manufacturePojo(clazz, genericTypeArgs);
    }

    /**
     * 模拟填充 Result POJO 返回
     *
     * @param clazz ResultVO 范型类
     * @param <T>   ResultVO 范型
     * @return ResultVO T 实例
     */
    public static <T> ResultVO<T> mockR(Class<T> clazz) {
        return ResultVO.getSuccess(mock(clazz));
    }

    /**
     * 模拟填充 PageVO POJO 返回
     *
     * @param clazz PageVO 范型类
     * @param <T>   PageVO 范型
     * @return PageVO T 实例
     */
    @SuppressWarnings("unchecked")
    public static <T> PageVO<T> mockP(Class<T> clazz) {
        return (PageVO<T>) PageVO.builder()
            .rows(mock(List.class, clazz))
            .totalPage(10)
            .pageSize(10)
            .total(100L)
            .pageNum(1)
            .nextPageNum(2)
            .build();
    }

    /**
     * 便捷方法组合 mockR + mockP
     *
     * @param clazz 范型类
     * @param <T>   范型
     * @return ResultVO - PageVo - T 实例
     */
    public static <T> ResultVO<PageVO<T>> mockRP(Class<T> clazz) {
        return ResultVO.getSuccess(mockP(clazz));
    }
}
